
#include "list.h"

DLINKLIST *llist_create(int initsize) 
{
	DLINKLIST *newlist;
	newlist = malloc(sizeof(*newlist));
	if(!newlist)
		return NULL;
	newlist->size = initsize;
	newlist->head.prev = &newlist->head;
	newlist->head.next = &newlist->head;
	return newlist;
}
void llist_destroy(DLINKLIST* ptr)
{
	struct  dllist_node_st * cur, * next;
	for (cur = ptr->head.next; cur != &ptr->head; cur = next)
	{
		next = cur->next;
		//free(cur->data);
		free(cur);
	}
	free(ptr);
}
int llist_insert(DLINKLIST * ptr, const void* data, int mode)
{
	struct dllist_node_st *newnode;
	newnode = malloc(sizeof(*newnode)+ ptr->size);
	if (!newnode)
		return -1;
	/*newnode->data = malloc(ptr->size);
	if (!newnode->data)
		return -2;*/
	memcpy(newnode->data, data, ptr->size);
	if (mode == FORWARD)
	{
		newnode->next = ptr->head.next;
		newnode->prev = &ptr->head;
	}
	else if (mode == BACKWARD)
	{
		newnode->prev = ptr->head.prev;
		newnode->next = &ptr->head;	
	}
	else
		return -3;
	newnode->prev->next = newnode;
	newnode->next->prev = newnode;
	return 0;
}
void llist_travel(DLINKLIST *ptr, llist_prt *op)
{
	struct  dllist_node_st* cur;
	for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next)
	{
		op(cur->data);
	}
}
static struct dllist_node_st* find_(DLINKLIST* ptr, const void* key, llist_cmp* cmp)
{
	struct  dllist_node_st* cur;
	for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next)
	{
		if (cmp(key, cur->data) == 0)
			break;
	}
	return cur;

}
void * llist_find(DLINKLIST* ptr, const void* key, llist_cmp* cmp) 
{
	struct dllist_node_st* node;
	node= find_(ptr, key, cmp);
	if (node == &ptr->head)
		return NULL;
	return node->data;
}
int llist_delete(DLINKLIST* ptr, const void* key, llist_cmp* cmp) 
{
	struct dllist_node_st *node;
	node = find_(ptr, key, cmp);
	if (node == &ptr->head)
		return -1;	
	node->prev->next = node->next;
	node->next->prev = node->prev;
	/*free(node->data);*/
	free(node);			
	return 0;
}

int llist_fetch(DLINKLIST* ptr, const void* key, llist_cmp* cmp, void* data)
{
	struct dllist_node_st* node;
	node = find_(ptr, key, cmp);
	if (node == &ptr->head)
		return -1;
	if (data != NULL)
		memcpy(data, node->data, ptr->size);
	node->prev->next = node->next;
	node->next->prev = node->prev;
	/*free(node->data);*/
	free(node);
	return 0;
}